package com.fa4j.product.category.service.impl;

import com.fa4j.common.base.exception.CommonRequestError;
import com.fa4j.common.base.model.DiffList;
import com.fa4j.common.base.model.RemoveCmd;
import com.fa4j.common.base.util.DiffListUtil;
import com.fa4j.product.category.convert.CategoryConverter;
import com.fa4j.product.category.model.Category;
import com.fa4j.product.category.model.CategoryAttribute;
import com.fa4j.product.category.model.CategoryCreateCmd;
import com.fa4j.product.category.model.CategoryModifyCmd;
import com.fa4j.product.category.repository.CategoryAttributeRepository;
import com.fa4j.product.category.repository.CategoryRepository;
import com.fa4j.product.category.service.CategoryService;
import com.fa4j.product.item.repository.ItemRepository;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.List;

/**
 * 服务实现-商品分类
 *
 * @since 2025-11-22 21:06:24
 */
@Slf4j
@Service
@Validated
@RequiredArgsConstructor
public class CategoryServiceImpl implements CategoryService {

    private final ItemRepository itemRepository;
    private final CategoryRepository categoryRepository;
    private final CategoryAttributeRepository categoryAttributeRepository;
    private final CategoryConverter categoryConverter;

    /**
     * 商品分类-创建
     *
     * @param cmd 创建参数
     * @return 商品分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Category create(@Valid CategoryCreateCmd cmd) {
        Category entity = categoryConverter.toEntity(cmd);
        categoryRepository.create(entity);
        saveAttribute(entity, null);
        return entity;
    }

    private void saveAttribute(Category entity, List<CategoryAttribute> exitAttrList) {
        DiffList<CategoryAttribute> diffList = DiffListUtil.diff(exitAttrList, entity.getAttrList(), CategoryAttribute::getName,
                (exist, obj) -> {
                    if (exist != null) {
                        obj.setId(exist.getId());
                        obj.setCreateTime(exist.getCreateTime());
                    }
                    obj.setOperatorId(entity.getOperatorId());
                }
        );
        for (CategoryAttribute createObj : diffList.createList()) {
            categoryAttributeRepository.create(createObj);
        }
        for (CategoryAttribute modifyObj : diffList.modifyList()) {
            categoryAttributeRepository.modify(modifyObj);
        }
        for (CategoryAttribute removeObj : diffList.removeList()) {
            categoryAttributeRepository.remove(removeObj);
        }
    }

    /**
     * 商品分类-编辑
     *
     * @param cmd 编辑参数
     * @return 商品分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Category modify(@Valid CategoryModifyCmd cmd) {
        Category entity = categoryRepository.findById(cmd.getId())
                .orElseThrow(() -> CommonRequestError.NOT_FOUND.build("商品分类"));
        List<CategoryAttribute> exitAttrList = entity.getAttrList();
        categoryConverter.updateEntity(entity, cmd);
        categoryRepository.modify(entity);
        saveAttribute(entity, exitAttrList);
        return entity;
    }

    /**
     * 商品分类-删除
     *
     * @param cmd 删除参数
     * @return 商品分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Category remove(@Valid RemoveCmd<Integer> cmd) {
        // 判断下级
        if (categoryRepository.countByParentId(cmd.getId()) > 0) {
            throw CommonRequestError.BAD_REQUEST.build("存在下级分类，不能被删除");
        }
        // 判断是否存在商品
        if (itemRepository.countByCategoryId(cmd.getId()) > 0) {
            throw CommonRequestError.BAD_REQUEST.build("分类下存在商品，不能被删除");
        }
        Category entity = categoryRepository.findById(cmd.getId())
                .orElseThrow(() -> CommonRequestError.NOT_FOUND.build("商品分类"));
        entity.setOperatorId(cmd.getOperatorId());
        categoryRepository.remove(entity);
        if (entity.getAttrList() != null) {
            for (CategoryAttribute attribute : entity.getAttrList()) {
                attribute.setOperatorId(cmd.getOperatorId());
                categoryAttributeRepository.remove(attribute);
            }
        }
        return entity;
    }


}






